# !/usr/bin/env python
# -*-coding:utf-8 -*-

"""
# File       : running_strategy.py
# Time       ：2023/8/1 10:26
# Author     ：YangYong
# version    ：python 3.10
# Description：
    获取运行中的任务
"""
import traceback

from sqlalchemy import desc

from apis.orderlines.models import TaskInstance, Task
from apis.orderlines.schema.task_schema import TaskInstanceSchema
from orderlines.utils.orderlines_enum import TaskStates
from orderlines.utils.utils import get_task_instance
from public.logger import logger
from public.utils.message_manager import RunningLoggerMessageManager
from public.utils.mongo_utils import MongoDBUtil
from public.base_model import session_scope


class RunningTask:
    def __init__(self, process_id, process_instance_id):
        self.process_id = process_id
        self.process_instance_id = process_instance_id
        self.mongo = MongoDBUtil('flow_data')
        self.pre_task_progress = 0

    def get_flow_data(self):
        """获取流程图中的流程数据"""
        filter_ = {'process_id': self.process_id}
        flow_data = self.mongo.collection.find_one(filter_)
        if isinstance(flow_data, dict) and '_id' in flow_data:
            flow_data.pop('_id')
        return flow_data

    def get_task_instances(self):
        """获取所有正在运行的任务实例"""
        with session_scope() as session:
            objs = session.query(TaskInstance).filter(
                TaskInstance.active == 1,
                TaskInstance.process_instance_id == self.process_instance_id
            ).all()
            return TaskInstanceSchema().dump(objs, many=True)

    def get_process_running_data(self):
        flow_data = self.get_flow_data()
        nodes = flow_data.get('graphData').get('nodes')
        if self.process_instance_id:
            task_instance_info = self.get_task_instances()
            for node in nodes:
                for task_instance in task_instance_info:
                    if node.get('id') == task_instance.get('task_id'):
                        properties = node.get('properties')
                        properties['status'] = task_instance.get('task_status')
        return flow_data

    def get_running_task_ids(self):
        """获取正在运行中的任务ID"""
        with session_scope() as session:
            objs = session.query(TaskInstance).filter(
                TaskInstance.active == 1,
                TaskInstance.task_status == TaskStates.blue.value,
                TaskInstance.process_instance_id == self.process_instance_id
            ).all()

            return TaskInstanceSchema().dump(objs, many=True)

    @staticmethod
    def check_task_id(task_id):
        """检查任务ID"""
        with session_scope() as session:
            obj = session.query(TaskInstance).filter(TaskInstance.task_id == task_id).first()
        return True if obj else False

    def task_progress(self, node_count: int):
        """计算任务进度"""
        try:
            with session_scope() as session:
                obj = session.query(TaskInstance).filter(
                    TaskInstance.process_instance_id == self.process_instance_id
                ).order_by(desc(TaskInstance.task_index_id)).first()
                task_instance_info = TaskInstanceSchema().dump(obj)
                task_index_id = task_instance_info.get('task_index_id')
                self.pre_task_progress = round(task_index_id / node_count * 100)
        except Exception as e:
            logger.error(f'获取任务进度失败::{e}, \n{traceback.format_exc()}')

    def running_info(self):
        """获取正在运行中的任务"""
        running_edge = list()
        flow_data = self.get_flow_data()
        if not flow_data:
            return {
                'running_edge': running_edge,
                'task_progress': self.pre_task_progress,
                'graph_data': []
            }
        else:
            running_task = self.get_running_task_ids()
            edges = flow_data.get('graphData').get('edges')
            nodes = flow_data.get('graphData').get('nodes')
            for item in running_task:
                for edge in edges:
                    source_node_id = edge.get('sourceNodeId')
                    task_id = item.get('task_id')
                    if edge.get('targetNodeId') == task_id and self.check_task_id(source_node_id):
                        running_edge.append(edge.get("id"))

            self.task_progress(self.get_process_running_num())
            return {
                'running_edge': running_edge,
                'task_progress': self.pre_task_progress,
                'graph_data': self.get_process_running_data()
            }

    def get_process_running_num(self):
        """获取流程中有多少个实际运行任务数量，流程图展示运行进度"""
        with session_scope() as session:
            return session.query(Task).filter(
                Task.process_id == self.process_id, Task.task_index_id.isnot(None), Task.active == 1).count()

    def send_message(self, task_instance_id):
        """发送消息"""
        running_info = self.running_info()
        running_info['running_task'] = get_task_instance(task_instance_id)
        RunningLoggerMessageManager().publish(running_info)
